Вход Регистрация
Файл: 14d9f24c296a886635c3d363a707badb/sape.php
Строк: 1301
<?php
/**
 * SAPE.ru - Интеллектуальная система купли-продажи ссылок
 *
 * PHP-клиент
 *
 * Вебмастеры! Не нужно ничего менять в этом файле!
 * Все настройки - через параметры при вызове кода.
 * Читайте: http://help.sape.ru/
 *
 * По всем вопросам обращайтесь на support@sape.ru
 *
 * class SAPE_base                 - базовый класс
 * class SAPE_client             - класс для вывода обычных ссылок
 * class SAPE_client_context     - класс для вывода контекстных сссылок
 * class SAPE_articles             - класс для вывода статей
 *
 * @version 1.1.7 от 08.11.2012
 */

/**
 * Основной класс, выполняющий всю рутину
 */
class SAPE_base {

    var 
$_version '1.1.7';

    var 
$_verbose false;

    var 
$_charset ''// http://www.php.net/manual/en/function.iconv.php

    
var $_sape_charset '';

    var 
$_server_list = array('dispenser-01.sape.ru''dispenser-02.sape.ru');

    var 
$_cache_lifetime 3600// Пожалейте наш сервер :о)

    // Если скачать базу ссылок не удалось, то следующая попытка будет через столько секунд
    
var $_cache_reloadtime 600;

    var 
$_error '';

    var 
$_host '';

    var 
$_request_uri '';

    var 
$_multi_site false;

    var 
$_fetch_remote_type ''// Способ подключения к удалённому серверу [file_get_contents|curl|socket]

    
var $_socket_timeout 6// Сколько ждать ответа

    
var $_force_show_code false;

    var 
$_is_our_bot false// Если наш робот

    
var $_debug false;

    var 
$_ignore_case false// Регистронезависимый режим работы, использовать только на свой страх и риск

    
var $_db_file ''// Путь к файлу с данными

    
var $_use_server_array false// Откуда будем брать uri страницы: $_SERVER['REQUEST_URI'] или getenv('REQUEST_URI')

    
var $_force_update_db false;

    var 
$_is_block_css_showed false// Флаг для отрисовки css в блочных ссылках

    
var $_is_block_ins_beforeall_showed false;

    function 
SAPE_base($options null) {

        
// Поехали :o)

        
$host '';

        if (
is_array($options)) {
            if (isset(
$options['host'])) {
                
$host $options['host'];
            }
        } elseif (
strlen($options)) {
            
$host $options;
            
$options = array();
        } else {
            
$options = array();
        }

        if (isset(
$options['use_server_array']) && $options['use_server_array'] == true) {
            
$this->_use_server_array true;
        }

        
// Какой сайт?
        
if (strlen($host)) {
            
$this->_host $host;
        } else {
            
$this->_host $_SERVER['HTTP_HOST'];
        }

        
$this->_host preg_replace('/^http:///'''$this->_host);
        
$this->_host preg_replace('/^www./'''$this->_host);

        
// Какая страница?
        
if (isset($options['request_uri']) && strlen($options['request_uri'])) {
            
$this->_request_uri $options['request_uri'];
        } elseif (
$this->_use_server_array === false) {
            
$this->_request_uri getenv('REQUEST_URI');
        }

        if (
strlen($this->_request_uri) == 0) {
            
$this->_request_uri $_SERVER['REQUEST_URI'];
        }

        
// На случай, если хочется много сайтов в одной папке
        
if (isset($options['multi_site']) && $options['multi_site'] == true) {
            
$this->_multi_site true;
        }

        
// Выводить информацию о дебаге
        
if (isset($options['debug']) && $options['debug'] == true) {
            
$this->_debug true;
        }

        
// Определяем наш ли робот
        
if (isset($_COOKIE['sape_cookie']) && ($_COOKIE['sape_cookie'] == _SAPE_USER)) {
            
$this->_is_our_bot true;
            if (isset(
$_COOKIE['sape_debug']) && ($_COOKIE['sape_debug'] == 1)) {
                
$this->_debug true;
                
//для удобства дебега саппортом
                
$this->_options $options;
                
$this->_server_request_uri $this->_request_uri $_SERVER['REQUEST_URI'];
                
$this->_getenv_request_uri getenv('REQUEST_URI');
                
$this->_SAPE_USER _SAPE_USER;
            }
            if (isset(
$_COOKIE['sape_updatedb']) && ($_COOKIE['sape_updatedb'] == 1)) {
                
$this->_force_update_db true;
            }
        } else {
            
$this->_is_our_bot false;
        }

        
// Сообщать об ошибках
        
if (isset($options['verbose']) && $options['verbose'] == true || $this->_debug) {
            
$this->_verbose true;
        }

        
// Кодировка
        
if (isset($options['charset']) && strlen($options['charset'])) {
            
$this->_charset $options['charset'];
        } else {
            
$this->_charset 'windows-1251';
        }

        if (isset(
$options['fetch_remote_type']) && strlen($options['fetch_remote_type'])) {
            
$this->_fetch_remote_type $options['fetch_remote_type'];
        }

        if (isset(
$options['socket_timeout']) && is_numeric($options['socket_timeout']) && $options['socket_timeout'] > 0) {
            
$this->_socket_timeout $options['socket_timeout'];
        }

        
// Всегда выводить чек-код
        
if (isset($options['force_show_code']) && $options['force_show_code'] == true) {
            
$this->_force_show_code true;
        }

        if (!
defined('_SAPE_USER')) {
            return 
$this->raise_error('Не задана константа _SAPE_USER');
        }

        
//Не обращаем внимания на регистр ссылок
        
if (isset($options['ignore_case']) && $options['ignore_case'] == true) {
            
$this->_ignore_case true;
            
$this->_request_uri strtolower($this->_request_uri);
        }
    }

    
/**
     * Функция для подключения к удалённому серверу
     */
    
function fetch_remote_file($host$path$specifyCharset false) {

        
$user_agent $this->_user_agent ' ' $this->_version;

        @
ini_set('allow_url_fopen'1);
        @
ini_set('default_socket_timeout'$this->_socket_timeout);
        @
ini_set('user_agent'$user_agent);
        if (
                
$this->_fetch_remote_type == 'file_get_contents'
                
||
                (
                        
$this->_fetch_remote_type == ''
                        
&&
                        
function_exists('file_get_contents')
                        &&
                        
ini_get('allow_url_fopen') == 1
                
)
        ) {
            
$this->_fetch_remote_type 'file_get_contents';
            
            if(
$specifyCharset && function_exists('stream_context_create')) {
                
$opts = array( 
                  
'http' => array( 
                    
'method' => 'GET'
                    
'header' => 'Accept-Charset: '$this->_charset"rn"
                  

                ); 
                
$context = @stream_context_create($opts);                     
                if (
$data = @file_get_contents('http://' $host $pathnull$context)) {
                    return 
$data;
                }
            } else {
                if (
$data = @file_get_contents('http://' $host $path)) {
                    return 
$data;
                }
            }
            
        } elseif (
                
$this->_fetch_remote_type == 'curl'
                
||
                (
                        
$this->_fetch_remote_type == ''
                        
&&
                        
function_exists('curl_init')
                )
        ) {
            
$this->_fetch_remote_type 'curl';
            if (
$ch = @curl_init()) {

                @
curl_setopt($chCURLOPT_URL'http://' $host $path);
                @
curl_setopt($chCURLOPT_HEADERfalse);
                @
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
                @
curl_setopt($chCURLOPT_CONNECTTIMEOUT$this->_socket_timeout);
                @
curl_setopt($chCURLOPT_USERAGENT$user_agent);
                if(
$specifyCharset) {
                    @
curl_setopt($chCURLOPT_HTTPHEADER, array('Accept-Charset: '$this->_charset));
                }

                
$data = @curl_exec($ch);
                @
curl_close($ch);

                if (
$data) {
                    return 
$data;
                }
            }

        } else {
            
$this->_fetch_remote_type 'socket';
            
$buff '';
            
$fp = @fsockopen($host80$errno$errstr$this->_socket_timeout);
            if (
$fp) {
                @
fputs($fp"GET {$path} HTTP/1.0rnHost: {$host}rn");
                if(
$specifyCharset) {
                    @
fputs($fp"Accept-Charset: {$this->_charset}rn");
                }
                @
fputs($fp"User-Agent: {$user_agent}rnrn");
                while (!@
feof($fp)) {
                    
$buff .= @fgets($fp128);
                }
                @
fclose($fp);

                
$page explode("rnrn"$buff);
                unset(
$page[0]);
                return 
implode("rnrn"$page);
            }

        }

        return 
$this->raise_error('Не могу подключиться к серверу: ' $host $path ', type: ' $this->_fetch_remote_type);
    }

    
/**
     * Функция чтения из локального файла
     */
    
function _read($filename) {

        
$fp = @fopen($filename'rb');
        @
flock($fpLOCK_SH);
        if (
$fp) {
            
clearstatcache();
            
$length = @filesize($filename);
            
$mqr = @get_magic_quotes_runtime();
            @
set_magic_quotes_runtime(0);
            if (
$length) {
                
$data = @fread($fp$length);
            } else {
                
$data '';
            }
                @
set_magic_quotes_runtime($mqr);
            @
flock($fpLOCK_UN);
            @
fclose($fp);

            return 
$data;
        }

        return 
$this->raise_error('Не могу считать данные из файла: ' $filename);
    }

    
/**
     * Функция записи в локальный файл
     */
    
function _write($filename$data) {

        
$fp = @fopen($filename'ab');
        if (
$fp) {
            if (
flock($fpLOCK_EX LOCK_NB)) {
                
ftruncate($fp0);
                
$mqr = @get_magic_quotes_runtime();
                @
set_magic_quotes_runtime(0);
                @
fwrite($fp$data);
                @
set_magic_quotes_runtime($mqr);
                @
flock($fpLOCK_UN);
                @
fclose($fp);

                if (
md5($this->_read($filename)) != md5($data)) {
                    @
unlink($filename);
                    return 
$this->raise_error('Нарушена целостность данных при записи в файл: ' $filename);
                }
            } else {
                return 
false;
            }

            return 
true;
        }

        return 
$this->raise_error('Не могу записать данные в файл: ' $filename);
    }

    
/**
     * Функция обработки ошибок
     */
    
function raise_error($e) {

        
$this->_error '<p style="color: red; font-weight: bold;">SAPE ERROR: ' $e '</p>';

        if (
$this->_verbose == true) {
            print 
$this->_error;
        }

        return 
false;
    }

    
/**
     * Загрузка данных
     */
    
function load_data() {
        
$this->_db_file $this->_get_db_file();

        if (!
is_file($this->_db_file)) {
            
// Пытаемся создать файл.
            
if (@touch($this->_db_file)) {
                @
chmod($this->_db_file0666); // Права доступа
            
} else {
                return 
$this->raise_error('Нет файла ' $this->_db_file '. Создать не удалось. Выставите права 777 на папку.');
            }
        }

        if (!
is_writable($this->_db_file)) {
            return 
$this->raise_error('Нет доступа на запись к файлу: ' $this->_db_file '! Выставите права 777 на папку.');
        }

        @
clearstatcache();

        
$data $this->_read($this->_db_file);
        if (
                
$this->_force_update_db
                
|| (
                        !
$this->_is_our_bot
                        
&&
                        (
                                
filemtime($this->_db_file) < (time() - $this->_cache_lifetime)
                                ||
                                
filesize($this->_db_file) == 0
                                
||
                                @
unserialize($data) == false
                        
)
                )
        ) {
            
// Чтобы не повесить площадку клиента и чтобы не было одновременных запросов
            
@touch($this->_db_file, (time() - $this->_cache_lifetime $this->_cache_reloadtime));

            
$path $this->_get_dispenser_path();
            if (
strlen($this->_charset)) {
                
$path .= '&charset=' $this->_charset;
            }

            foreach (
$this->_server_list as $i => $server) {
                if (
$data $this->fetch_remote_file($server$path)) {
                    if (
substr($data012) == 'FATAL ERROR:') {
                        
$this->raise_error($data);
                    } else {
                        
// [псевдо]проверка целостности:
                        
$hash = @unserialize($data);
                        if (
$hash != false) {
                            
// попытаемся записать кодировку в кеш
                            
$hash['__sape_charset__'] = $this->_charset;
                            
$hash['__last_update__'] = time();
                            
$hash['__multi_site__'] = $this->_multi_site;
                            
$hash['__fetch_remote_type__'] = $this->_fetch_remote_type;
                            
$hash['__ignore_case__'] = $this->_ignore_case;
                            
$hash['__php_version__'] = phpversion();
                            
$hash['__server_software__'] = $_SERVER['SERVER_SOFTWARE'];

                            
$data_new = @serialize($hash);
                            if (
$data_new) {
                                
$data $data_new;
                            }

                            
$this->_write($this->_db_file$data);
                            break;
                        }
                    }
                }
            }
        }

        
// Убиваем PHPSESSID
        
if (strlen(session_id())) {
            
$session session_name() . '=' session_id();
            
$this->_request_uri str_replace(array('?' $session'&' $session), ''$this->_request_uri);
        }

        
$this->set_data(@unserialize($data));
    }
}

/**
 * Класс для работы с обычными ссылками
 */
class SAPE_client extends SAPE_base {

    var 
$_links_delimiter '';
    var 
$_links = array();
    var 
$_links_page = array();
    var 
$_user_agent 'SAPE_Client PHP';

    function 
SAPE_client($options null) {
        
parent::SAPE_base($options);
        
$this->load_data();
    }

    
/**
     * Обработка html для массива ссылок
     *
     * @param string $html
     * @return string
     */
    
function _return_array_links_html($html$options null) {

        if(empty(
$options)) {
            
$options = array();
        }

        
// если запрошена определенная кодировка, и известна кодировка кеша, и они разные, конвертируем в заданную
        
if (
                
strlen($this->_charset) > 0
                
&&
                
strlen($this->_sape_charset) > 0
                
&&
                
$this->_sape_charset != $this->_charset
                
&&
                
function_exists('iconv')
        ) {
            
$new_html = @iconv($this->_sape_charset$this->_charset$html);
            if (
$new_html) {
                
$html $new_html;
            }
        }

        if (
$this->_is_our_bot) {

            
$html '<sape_noindex>' $html '</sape_noindex>';

            if(isset(
$options['is_block_links']) && true == $options['is_block_links']) {

                if(!isset(
$options['nof_links_requested'])) {
                    
$options['nof_links_requested'] = 0;
                }
                if(!isset(
$options['nof_links_displayed'])) {
                    
$options['nof_links_displayed'] = 0;
                }
                if(!isset(
$options['nof_obligatory'])) {
                    
$options['nof_obligatory'] = 0;
                }
                if(!isset(
$options['nof_conditional'])) {
                    
$options['nof_conditional'] = 0;
                }

                
$html '<sape_block nof_req="' $options['nof_links_requested'] .
                            
'" nof_displ="' $options['nof_links_displayed'] .
                            
'" nof_oblig="' $options['nof_obligatory'] .
                            
'" nof_cond="' $options['nof_conditional'] .
                            
'">' $html .
                        
'</sape_block>';
            }
        }

        return 
$html;
    }

    
/**
     * Финальная обработка html перед выводом ссылок
     *
     * @param string $html
     * @return string
     */
    
function _return_html($html) {

         if (
$this->_debug) {
            
$html .= print_r($thistrue);
        }

        return 
$html;
    }

    
/**
     * Вывод ссылок в виде блока
     *
     * @param int $n Количествово
     * @param int $offset Смещение
     * @param array $options Опции
     *
     * <code>
     * $options = array();
     * $options['block_no_css'] = (false|true);
     * // Переопределяет запрет на вывод css в коде страницы: false - выводить css
     * $options['block_orientation'] = (1|0);
     * // Переопределяет ориентацию блока: 1 - горизонтальная, 0 - вертикальная
     * $options['block_width'] = ('auto'|'[?]px'|'[?]%'|'[?]');
     * // Переопределяет ширину блока:
     * // 'auto'  - определяется шириной блока-предка с фиксированной шириной,
     * // если такового нет, то займет всю ширину
     * // '[?]px' - значение в пикселях
     * // '[?]%'  - значение в процентах от ширины блока-предка с фиксированной шириной
     * // '[?]'   - любое другое значение, которое поддерживается спецификацией CSS
     * </code>
     *
     * @return string
     */
    
function return_block_links($n null$offset 0$options null) {

        
// Объединить параметры
        
if(empty($options)) {
            
$options = array();
        }

        
$defaults = array();
        
$defaults['block_no_css']         = false;
        
$defaults['block_orientation']     = 1;
        
$defaults['block_width']         = '';

        
$ext_options = array();
        if(isset(
$this->_block_tpl_options) && is_array($this->_block_tpl_options)) {
            
$ext_options $this->_block_tpl_options;
        }

        
$options array_merge($defaults$ext_options$options);

        
// Ссылки переданы не массивом (чек-код) => выводим как есть + инфо о блоке
        
if (!is_array($this->_links_page)) {
            
$html $this->_return_array_links_html('', array('is_block_links' => true));
            return 
$this->_return_html($this->_links_page $html);
        }
        
// Не переданы шаблоны => нельзя вывести блоком - ничего не делать
        
elseif(!isset($this->_block_tpl)) {
            return 
$this->_return_html('');
        }

        
// Определим нужное число элементов в блоке

        
$total_page_links count($this->_links_page);

        
$need_show_obligatory_block false;
        
$need_show_conditional_block false;
        
$n_requested 0;

        if(isset(
$this->_block_ins_itemobligatory)) {
            
$need_show_obligatory_block true;
        }

        if(
is_numeric($n) && $n >= $total_page_links) {

            
$n_requested $n;

            if(isset(
$this->_block_ins_itemconditional)) {
                
$need_show_conditional_block true;
            }
        }

        if (!
is_numeric($n) || $n $total_page_links) {
            
$n $total_page_links;
        }

        
// Выборка ссылок
        
$links = array();
        for (
$i 1$i <= $n$i++) {
            if (
$offset && $i <= $offset) {
                
array_shift($this->_links_page);
            } else {
                
$links[] = array_shift($this->_links_page);
            }
        }

        
$html '';

        
// Подсчет числа опциональных блоков
        
$nof_conditional 0;
        if(
count($links) < $n_requested && true == $need_show_conditional_block) {
            
$nof_conditional $n_requested count($links);
        }

        
//Если нет ссылок и нет вставных блоков, то ничего не выводим
        
if(empty($links) && $need_show_obligatory_block == false && $nof_conditional == 0) {

            
$return_links_options = array(
                
'is_block_links'         => true,
                
'nof_links_requested'     => $n_requested,
                
'nof_links_displayed'    => 0,
                
'nof_obligatory'        => 0,
                
'nof_conditional'        => 0
            
);

            
$html $this->_return_array_links_html($html$return_links_options);

            return 
$this->_return_html($html);
        }

        
// Делаем вывод стилей, только один раз. Или не выводим их вообще, если так задано в параметрах
        
if (!$this->_is_block_css_showed && false == $options['block_no_css']) {
            
$html .= $this->_block_tpl['css'];
            
$this->_is_block_css_showed true;
        }

        
// Вставной блок в начале всех блоков
        
if (isset($this->_block_ins_beforeall) && !$this->_is_block_ins_beforeall_showed){
            
$html .= $this->_block_ins_beforeall;
            
$this->_is_block_ins_beforeall_showed true;
        }

        
// Вставной блок в начале блока
        
if (isset($this->_block_ins_beforeblock)){
            
$html .= $this->_block_ins_beforeblock;
        }

        
// Получаем шаблоны в зависимости от ориентации блока
        
$block_tpl_parts $this->_block_tpl[$options['block_orientation']];

        
$block_tpl             $block_tpl_parts['block'];
        
$item_tpl             $block_tpl_parts['item'];
        
$item_container_tpl $block_tpl_parts['item_container'];
        
$item_tpl_full         str_replace('{item}'$item_tpl$item_container_tpl);
        
$items                 '';

        
$nof_items_total count($links);
        foreach (
$links as $link){

            
preg_match('#<a href="(https?://([^"/]+)[^"]*)"[^>]*>[s]*([^<]+)</a>#i'$link$link_item);

            if (
function_exists('mb_strtoupper') && strlen($this->_sape_charset) > 0) {
                
$header_rest mb_substr($link_item[3], 1mb_strlen($link_item[3], $this->_sape_charset) - 1$this->_sape_charset);
                
$header_first_letter mb_strtoupper(mb_substr($link_item[3], 01$this->_sape_charset), $this->_sape_charset);
                
$link_item[3] = $header_first_letter $header_rest;
            } elseif(
function_exists('ucfirst') && (strlen($this->_sape_charset) == || strpos($this->_sape_charset'1251') !== false) ) {
                
$link_item[3][0] = ucfirst($link_item[3][0]);
            }

            
// Если есть раскодированный URL, то заменить его при выводе

            
if(isset($this->_block_uri_idna) && isset($this->_block_uri_idna[$link_item[2]])) {
                
$link_item[2] = $this->_block_uri_idna[$link_item[2]];
            }

            
$item $item_tpl_full;
            
$item str_replace('{header}'$link_item[3], $item);
            
$item str_replace('{text}'trim($link), $item);
            
$item str_replace('{url}'$link_item[2], $item);
            
$item str_replace('{link}'$link_item[1], $item);
            
$items .= $item;
        }

        
// Вставной обязатльный элемент в блоке
        
if(true == $need_show_obligatory_block) {
            
$items .= str_replace('{item}'$this->_block_ins_itemobligatory$item_container_tpl);
            
$nof_items_total += 1;
        }

        
// Вставные опциональные элементы в блоке
        
if($need_show_conditional_block == true && $nof_conditional 0) {
            for(
$i 0$i $nof_conditional$i++) {
                
$items .= str_replace('{item}'$this->_block_ins_itemconditional$item_container_tpl);
            }
            
$nof_items_total += $nof_conditional;
        }

        if (
$items != ''){
            
$html .= str_replace('{items}'$items$block_tpl);

            
// Проставляем ширину, чтобы везде одинковая была
            
if ($nof_items_total 0){
                
$html str_replace('{td_width}'round(100/$nof_items_total), $html);
            } else {
                
$html str_replace('{td_width}'0$html);
            }

            
// Если задано, то переопределить ширину блока
            
if(isset($options['block_width']) && !empty($options['block_width'])) {
                
$html str_replace('{block_style_custom}''style="width: ' $options['block_width'] . '!important;"'$html);
            }
        }

        unset(
$block_tpl_parts$block_tpl$items$item$item_tpl$item_container_tpl);

        
// Вставной блок в конце блока
        
if (isset($this->_block_ins_afterblock)){
            
$html .= $this->_block_ins_afterblock;
        }

        
//Заполняем оставшиеся модификаторы значениями
        
unset($options['block_no_css'], $options['block_orientation'], $options['block_width']);

        
$tpl_modifiers array_keys($options);
        foreach(
$tpl_modifiers as $k=>$m) {
            
$tpl_modifiers[$k] = '{' $m '}';
        }
        unset(
$m$k);

        
$tpl_modifiers_values =  array_values($options);

        
$html str_replace($tpl_modifiers$tpl_modifiers_values$html);
        unset(
$tpl_modifiers$tpl_modifiers_values);

        
//Очищаем незаполненные модификаторы
        
$clear_modifiers_regexp '#{[a-zd_-]+}#';
        
$html preg_replace($clear_modifiers_regexp' '$html);

        
$return_links_options = array(
            
'is_block_links'         => true,
            
'nof_links_requested'     => $n_requested,
            
'nof_links_displayed'    => $n,
            
'nof_obligatory'        => ($need_show_obligatory_block == true 0),
            
'nof_conditional'        => $nof_conditional
        
);

        
$html $this->_return_array_links_html($html$return_links_options);

        return 
$this->_return_html($html);
    }

    
/**
     * Вывод ссылок в обычном виде - текст с разделителем
     *
     * @param int $n Количествово
     * @param int $offset Смещение
     * @param array $options Опции
     *
     * <code>
     * $options = array();
     * $options['as_block'] = (false|true);
     * // Показывать ли ссылки в виде блока
     * </code>
     *
     * @see return_block_links()
     * @return string
     */
    
function return_links($n null$offset 0$options null) {

        
//Опрелелить, как выводить ссылки
        
$as_block $this->_show_only_block;

        if(
is_array($options) && isset($options['as_block']) && false == $as_block) {
            
$as_block $options['as_block'];
        }

        if(
true == $as_block && isset($this->_block_tpl)) {
            return 
$this->return_block_links($n$offset$options);
        }

        
//-------

        
if (is_array($this->_links_page)) {

            
$total_page_links count($this->_links_page);

            if (!
is_numeric($n) || $n $total_page_links) {
                
$n $total_page_links;
            }

            
$links = array();

            for (
$i 1$i <= $n$i++) {
                if (
$offset && $i <= $offset) {
                    
array_shift($this->_links_page);
                } else {
                    
$links[] = array_shift($this->_links_page);
                }
            }

            
$html join($this->_links_delimiter$links);

            
// если запрошена определенная кодировка, и известна кодировка кеша, и они разные, конвертируем в заданную
            
if (
                    
strlen($this->_charset) > 0
                    
&&
                    
strlen($this->_sape_charset) > 0
                    
&&
                    
$this->_sape_charset != $this->_charset
                    
&&
                    
function_exists('iconv')
            ) {
                
$new_html = @iconv($this->_sape_charset$this->_charset$html);
                if (
$new_html) {
                    
$html $new_html;
                }
            }

            if (
$this->_is_our_bot) {
                
$html '<sape_noindex>' $html '</sape_noindex>';
            }
        } else {
            
$html $this->_links_page;
            if (
$this->_is_our_bot) {
                
$html .= '<sape_noindex></sape_noindex>';
            }
        }

        if (
$this->_debug) {
            
$html .= print_r($thistrue);
        }

        return 
$html;
    }

    function 
_get_db_file() {
        if (
$this->_multi_site) {
            return 
dirname(__FILE__) . '/' $this->_host '.links.db';
        } else {
            return 
dirname(__FILE__) . '/links.db';
        }
    }

    function 
_get_dispenser_path() {
        return 
'/code.php?user=' _SAPE_USER '&host=' $this->_host;
    }

    function 
set_data($data) {
        if (
$this->_ignore_case) {
            
$this->_links array_change_key_case($data);
        } else {
            
$this->_links $data;
        }
        if (isset(
$this->_links['__sape_delimiter__'])) {
            
$this->_links_delimiter $this->_links['__sape_delimiter__'];
        }
        
// определяем кодировку кеша
        
if (isset($this->_links['__sape_charset__'])) {
            
$this->_sape_charset $this->_links['__sape_charset__'];
        } else {
            
$this->_sape_charset '';
        }
        if (@
array_key_exists($this->_request_uri$this->_links) && is_array($this->_links[$this->_request_uri])) {
            
$this->_links_page $this->_links[$this->_request_uri];
        } else {
            if (isset(
$this->_links['__sape_new_url__']) && strlen($this->_links['__sape_new_url__'])) {
                if (
$this->_is_our_bot || $this->_force_show_code) {
                    
$this->_links_page $this->_links['__sape_new_url__'];
                }
            }
        }

        
// Есть ли флаг блочных ссылок
        
if (isset($this->_links['__sape_show_only_block__'])) {
            
$this->_show_only_block $this->_links['__sape_show_only_block__'];
        }
        else {
            
$this->_show_only_block false;
        }

        
// Есть ли шаблон для красивых ссылок
        
if (isset($this->_links['__sape_block_tpl__']) && !empty($this->_links['__sape_block_tpl__'])
                && 
is_array($this->_links['__sape_block_tpl__'])){
            
$this->_block_tpl $this->_links['__sape_block_tpl__'];
        }

        
// Есть ли параметры для красивых ссылок
        
if (isset($this->_links['__sape_block_tpl_options__']) && !empty($this->_links['__sape_block_tpl_options__'])
                && 
is_array($this->_links['__sape_block_tpl_options__'])){
            
$this->_block_tpl_options $this->_links['__sape_block_tpl_options__'];
        }

        
// IDNA-домены
        
if (isset($this->_links['__sape_block_uri_idna__']) && !empty($this->_links['__sape_block_uri_idna__'])
                && 
is_array($this->_links['__sape_block_uri_idna__'])){
            
$this->_block_uri_idna $this->_links['__sape_block_uri_idna__'];
        }

        
// Блоки
        
$check_blocks = array(
            
'beforeall',
            
'beforeblock',
            
'afterblock',
            
'itemobligatory',
            
'itemconditional',
            
'afterall'
        
);

        foreach(
$check_blocks as $block_name) {

            
$var_name '__sape_block_ins_' $block_name '__';
            
$prop_name '_block_ins_' $block_name;

            if (isset(
$this->_links[$var_name]) && strlen($this->_links[$var_name]) > 0) {
                
$this->$prop_name $this->_links[$var_name];
            }

        }
    }
}

/**
 * Класс для работы с контекстными ссылками
 */
class SAPE_context extends SAPE_base {

    var 
$_words = array();
    var 
$_words_page = array();
    var 
$_user_agent 'SAPE_Context PHP';
    var 
$_filter_tags = array('a''textarea''select''script''style''label''noscript''noindex''button');

    function 
SAPE_context($options null) {
        
parent::SAPE_base($options);
        
$this->load_data();
    }

    
/**
     * Замена слов в куске текста и обрамляет его тегами sape_index
     */
    
function replace_in_text_segment($text) {
        
$debug '';
        if (
$this->_debug) {
            
$debug .= "<!-- argument for replace_in_text_segment: rn" base64_encode($text) . "rn -->";
        }
        if (
count($this->_words_page) > 0) {

            
$source_sentence = array();
            if (
$this->_debug) {
                
$debug .= '<!-- sentences for replace: ';
            }
            
//Создаем массив исходных текстов для замены
            
foreach ($this->_words_page as $n => $sentence) {
                
//Заменяем все сущности на символы
                
$special_chars = array(
                    
'&amp;' => '&',
                    
'&quot;' => '"',
                    
'&#039;' => ''',
                    '
&lt;' => '<',
                    '
&gt;' => '>'
                );
                $sentence = strip_tags($sentence);
                foreach ($special_chars as $from => $to) {
                    str_replace($from, $to, $sentence);
                }
                //Преобразуем все спец символы в сущности
                $sentence = htmlspecialchars($sentence);
                //Квотируем
                $sentence = preg_quote($sentence, '
/');
                $replace_array = array();
                if (preg_match_all('
/(&[#a-zA-Z0-9]{2,6};)/isU', $sentence, $out)) {
                    
for ($i 0$i count($out[1]); $i++) {
                        
$unspec $special_chars[$out[1][$i]];
                        
$real $out[1][$i];
                        
$replace_array[$unspec] = $real;
                    }
                }
                
//Заменяем сущности на ИЛИ (сущность|символ)
                
foreach ($replace_array as $unspec => $real) {
                    
$sentence str_replace($real'((' $real ')|(' $unspec '))'$sentence);
                }
                
//Заменяем пробелы на переносы или сущности пробелов
                
$source_sentences[$n] = str_replace(' ''((s)|(&nbsp;))+'$sentence);

                if (
$this->_debug) {
                    
$debug .= $source_sentences[$n] . "rnrn";
                }
            }

            if (
$this->_debug) {
                
$debug .= '-->';
            }

            
//если это первый кусок, то не будем добавлять <
            
$first_part true;
            
//пустая переменная для записи

            
if (count($source_sentences) > 0) {

                
$content '';
                
$open_tags = array(); //Открытые забаненые тэги
                
$close_tag ''//Название текущего закрывающего тэга

                //Разбиваем по символу начала тега
                
$part strtok(' ' $text'<');

                while (
$part !== false) {
                    
//Определяем название тэга
                    
if (preg_match('/(?si)^(/?[a-z0-9]+)/'$part$matches)) {
                        
//Определяем название тега
                        
$tag_name strtolower($matches[1]);
                        
//Определяем закрывающий ли тэг
                        
if (substr($tag_name01) == '/') {
                            
$close_tag substr($tag_name1);
                            if (
$this->_debug) {
                                
$debug .= '<!-- close_tag: ' $close_tag ' -->';
                            }
                        } else {
                            
$close_tag '';
                            if (
$this->_debug) {
                                
$debug .= '<!-- open_tag: ' $tag_name ' -->';
                            }
                        }
                        
$cnt_tags count($open_tags);
                        
//Если закрывающий тег совпадает с тегом в стеке открытых запрещенных тегов
                        
if (($cnt_tags 0) && ($open_tags[$cnt_tags 1] == $close_tag)) {
                            
array_pop($open_tags);
                            if (
$this->_debug) {
                                
$debug .= '<!-- ' $tag_name ' - deleted from open_tags -->';
                            }
                            if (
$cnt_tags == 0) {
                                if (
$this->_debug) {
                                    
$debug .= '<!-- start replacement -->';
                                }
                            }
                        }

                        
//Если нет открытых плохих тегов, то обрабатываем
                        
if (count($open_tags) == 0) {
                            
//если не запрещенный тэг, то начинаем обработку
                            
if (!in_array($tag_name$this->_filter_tags)) {
                                
$split_parts explode('>'$part2);
                                
//Перестраховываемся
                                
if (count($split_parts) == 2) {
                                    
//Начинаем перебор фраз для замены
                                    
foreach ($source_sentences as $n => $sentence) {
                                        if (
preg_match('/' $sentence '/'$split_parts[1]) == 1) {
                                            
$split_parts[1] = preg_replace('/' $sentence '/'str_replace('$''$'$this->_words_page[$n]), $split_parts[1], 1);
                                            if (
$this->_debug) {
                                                
$debug .= '<!-- ' $sentence ' --- ' $this->_words_page[$n] . ' replaced -->';
                                            }

                                            
//Если заменили, то удаляем строчку из списка замены
                                            
unset($source_sentences[$n]);
                                            unset(
$this->_words_page[$n]);
                                        }
                                    }
                                    
$part $split_parts[0] . '>' $split_parts[1];
                                    unset(
$split_parts);
                                }
                            } else {
                                
//Если у нас запрещеный тэг, то помещаем его в стек открытых
                                
$open_tags[] = $tag_name;
                                if (
$this->_debug) {
                                    
$debug .= '<!-- ' $tag_name ' - added to open_tags, stop replacement -->';
                                }
                            }
                        }
                    } else {
                        
//Если нет названия тега, то считаем, что перед нами текст
                        
foreach ($source_sentences as $n => $sentence) {
                            if (
preg_match('/' $sentence '/'$part) == 1) {
                                
$part preg_replace('/' $sentence '/'str_replace('$''$'$this->_words_page[$n]), $part1);

                                if (
$this->_debug) {
                                    
$debug .= '<!-- ' $sentence ' --- ' $this->_words_page[$n] . ' replaced -->';
                                }

                                
//Если заменили, то удаляем строчку из списка замены,
                                //чтобы было можно делать множественный вызов
                                
unset($source_sentences[$n]);
                                unset(
$this->_words_page[$n]);
                            }
                        }
                    }

                    
//Если у нас режим дебагинга, то выводим
                    
if ($this->_debug) {
                        
$content .= $debug;
                        
$debug '';
                    }
                    
//Если это первая часть, то не выводим <
                    
if ($first_part) {
                        
$content .= $part;
                        
$first_part false;
                    } else {
                        
$content .= $debug '<' $part;
                    }
                    
//Получаем следующу часть
                    
unset($part);
                    
$part strtok('<');
                }
                
$text ltrim($content);
                unset(
$content);
            }
        } else {
            if (
$this->_debug) {
                
$debug .= '<!-- No word`s for page -->';
            }
        }

        if (
$this->_debug) {
            
$debug .= '<!-- END: work of replace_in_text_segment() -->';
        }

        if (
$this->_is_our_bot || $this->_force_show_code || $this->_debug) {
            
$text '<sape_index>' $text '</sape_index>';
            if (isset(
$this->_words['__sape_new_url__']) && strlen($this->_words['__sape_new_url__'])) {
                
$text .= $this->_words['__sape_new_url__'];
            }
        }

        if (
$this->_debug) {
            if (
count($this->_words_page) > 0) {
                
$text .= '<!-- Not replaced: ' "rn";
                foreach (
$this->_words_page as $n => $value) {
                    
$text .= $value "rnrn";
                }
                
$text .= '-->';
            }

            
$text .= $debug;
        }
        return 
$text;
    }

    
/**
     * Замена слов
     */
    
function replace_in_page(&$buffer) {

        if (
count($this->_words_page) > 0) {
            
//разбиваем строку по sape_index
            //Проверяем есть ли теги sape_index
            
$split_content preg_split('/(?smi)(</?sape_index>)/'$buffer, -1);
            
$cnt_parts count($split_content);
            if (
$cnt_parts 1) {
                
//Если есть хоть одна пара sape_index, то начинаем работу
                
if ($cnt_parts >= 3) {
                    for (
$i 1$i $cnt_parts$i $i 2) {
                        
$split_content[$i] = $this->replace_in_text_segment($split_content[$i]);
                    }
                }
                
$buffer implode(''$split_content);
                if (
$this->_debug) {
                    
$buffer .= '<!-- Split by Sape_index cnt_parts=' $cnt_parts '-->';
                }
            } else {
                
//Если не нашли sape_index, то пробуем разбить по BODY
                
$split_content preg_split('/(?smi)(</?body[^>]*>)/'$buffer, -1PREG_SPLIT_DELIM_CAPTURE);
                
//Если нашли содержимое между body
                
if (count($split_content) == 5) {
                    
$split_content[0] = $split_content[0] . $split_content[1];
                    
$split_content[1] = $this->replace_in_text_segment($split_content[2]);
                    
$split_content[2] = $split_content[3] . $split_content[4];
                    unset(
$split_content[3]);
                    unset(
$split_content[4]);
                    
$buffer $split_content[0] . $split_content[1] . $split_content[2];
                    if (
$this->_debug) {
                        
$buffer .= '<!-- Split by BODY -->';
                    }
                } else {
                    
//Если не нашли sape_index и не смогли разбить по body
                    
if ($this->_debug) {
                        
$buffer .= '<!-- Can`t split by BODY -->';
                    }
                }
            }

        } else {
            if (!
$this->_is_our_bot && !$this->_force_show_code && !$this->_debug) {
                
$buffer preg_replace('/(?smi)(</?sape_index>)/'''$buffer);
            } else {
                if (isset(
$this->_words['__sape_new_url__']) && strlen($this->_words['__sape_new_url__'])) {
                    
$buffer .= $this->_words['__sape_new_url__'];
                }
            }
            if (
$this->_debug) {
                
$buffer .= '<!-- No word`s for page -->';
            }
        }
        return 
$buffer;
    }

    function 
_get_db_file() {
        if (
$this->_multi_site) {
            return 
dirname(__FILE__) . '/' $this->_host '.words.db';
        } else {
            return 
dirname(__FILE__) . '/words.db';
        }
    }

    function 
_get_dispenser_path() {
        return 
'/code_context.php?user=' _SAPE_USER '&host=' $this->_host;
    }

    function 
set_data($data) {
        
$this->_words $data;
        if (@
array_key_exists($this->_request_uri$this->_words) && is_array($this->_words[$this->_request_uri])) {
            
$this->_words_page $this->_words[$this->_request_uri];
        }
    }
}

/**
 * Класс для работы со статьями articles.sape.ru показывает анонсы и статьи
 */
class SAPE_articles extends SAPE_base {

    var 
$_request_mode;

    var 
$_server_list             = array('dispenser.articles.sape.ru');

    var 
$_data                    = array();

    var 
$_article_id;

    var 
$_save_file_name;

    var 
$_announcements_delimiter '';

    var 
$_images_path;

    var 
$_template_error false;

    var 
$_noindex_code '<!--sape_noindex-->';

    var 
$_headers_enabled false;

    var 
$_mask_code;

    var 
$_real_host;
    
    var 
$_user_agent 'SAPE_Articles_Client PHP';

    function 
SAPE_articles($options null){
        
parent::SAPE_base($options);
        if (
is_array($options) && isset($options['headers_enabled'])) {
            
$this->_headers_enabled $options['headers_enabled'];
        }
        
// Кодировка
        
if (isset($options['charset']) && strlen($options['charset'])) {
            
$this->_charset $options['charset'];
        } else {
            
$this->_charset '';
        }
        
$this->_get_index();
        if (!empty(
$this->_data['index']['announcements_delimiter'])) {
            
$this->_announcements_delimiter $this->_data['index']['announcements_delimiter'];
        }
        if (!empty(
$this->_data['index']['charset'])
            and !(isset(
$options['charset']) && strlen($options['charset']))) {
            
$this->_charset $this->_data['index']['charset'];
        }
        if (
is_array($options)) {
            if (isset(
$options['host'])) {
                
$host $options['host'];
            }
        } elseif (
strlen($options)) {
            
$host $options;
            
$options = array();
        }
        if (isset(
$host) && strlen($host)) {
             
$this->_real_host $host;
        } else {
             
$this->_real_host $_SERVER['HTTP_HOST'];
        }
        if (!isset(
$this->_data['index']['announcements'][$this->_request_uri])) {
            
$this->_correct_uri();
        }
    }

    function 
_correct_uri() {
        if(
substr($this->_request_uri, -1) == '/') {
            
$new_uri substr($this->_request_uri0, -1);
        } else {
            
$new_uri $this->_request_uri '/';
        }
        if (isset(
$this->_data['index']['announcements'][$new_uri])) {
            
$this->_request_uri $new_uri;
        }
    }

    
/**
     * Возвращает анонсы для вывода
     * @param int $n      Сколько анонсов вывести, либо не задано - вывести все
     * @param int $offset C какого анонса начинаем вывод(нумерация с 0), либо не задано - с нулевого
     * @return string
     */
    
function return_announcements($n null$offset 0){
        
$output '';
        if (
$this->_force_show_code || $this->_is_our_bot) {
            if (isset(
$this->_data['index']['checkCode'])) {
                
$output .= $this->_data['index']['checkCode'];
            }
        }

        if (isset(
$this->_data['index']['announcements'][$this->_request_uri])) {

            
$total_page_links count($this->_data['index']['announcements'][$this->_request_uri]);

            if (!
is_numeric($n) || $n $total_page_links) {
                
$n $total_page_links;
            }

            
$links = array();

            for (
$i 1$i <= $n$i++) {
                if (
$offset && $i <= $offset) {
                    
array_shift($this->_data['index']['announcements'][$this->_request_uri]);
                } else {
                    
$links[] = array_shift($this->_data['index']['announcements'][$this->_request_uri]);
                }
            }

            
$html join($this->_announcements_delimiter$links);

            if (
$this->_is_our_bot) {
                
$html '<sape_noindex>' $html '</sape_noindex>';
            }

            
$output .= $html;

        }

        return 
$output;
    }

    function 
_get_index(){
        
$this->_set_request_mode('index');
        
$this->_save_file_name 'articles.db';
        
$this->load_data();
    }

    
/**
     * Возвращает полный HTML код страницы статьи
     * @return string
     */
    
function process_request(){

        if (!empty(
$this->_data['index']) and isset($this->_data['index']['articles'][$this->_request_uri])) {
            return 
$this->_return_article();
        } elseif (!empty(
$this->_data['index']) and isset($this->_data['index']['images'][$this->_request_uri])) {
            return 
$this->_return_image();
          } else {
                if (
$this->_is_our_bot) {
                    return 
$this->_return_html($this->_data['index']['checkCode'] . $this->_noindex_code);
                } else {
                    return 
$this->_return_not_found();
                }
          }
    }

    function 
_return_article(){
        
$this->_set_request_mode('article');
        
//Загружаем статью
        
$article_meta $this->_data['index']['articles'][$this->_request_uri];
        
$this->_save_file_name $article_meta['id'] . '.article.db';
        
$this->_article_id $article_meta['id'];
        
$this->load_data();

        
//Обновим если устарела
        
if (!isset($this->_data['article']['date_updated']) OR $this->_data['article']['date_updated']  < $article_meta['date_updated']) {
            
unlink($this->_get_db_file());
            
$this->load_data();
        }

        
//Получим шаблон
        
$template $this->_get_template($this->_data['index']['templates'][$article_meta['template_id']]['url'], $article_meta['template_id']);

        
//Выведем статью
        
$article_html $this->_fetch_article($template);

        if (
$this->_is_our_bot) {
            
$article_html .= $this->_noindex_code;
        }

        return 
$this->_return_html($article_html);

    }

    function 
_prepare_path_to_images(){
        
$this->_images_path dirname(__FILE__) . '/images/';
        if (!
is_dir($this->_images_path)) {
            
// Пытаемся создать папку.
            
if (@mkdir($this->_images_path)) {
                @
chmod($this->_images_path0777);    // Права доступа
            
} else {
                return 
$this->raise_error('Нет папки ' $this->_images_path '. Создать не удалось. Выставите права 777 на папку.');
              }
        }
        if (
$this->_multi_site) {
            
$this->_images_path .= $this->_host'.';
        }        
    }

    function 
_return_image(){
        
$this->_set_request_mode('image');
        
$this->_prepare_path_to_images();

        
//Проверим загружена ли картинка
        
$image_meta $this->_data['index']['images'][$this->_request_uri];
        
$image_path $this->_images_path $image_meta['id']. '.' $image_meta['ext'];

        if (!
is_file($image_path) or filemtime($image_path) > $image_meta['date_updated']) {
            
// Чтобы не повесить площадку клиента и чтобы не было одновременных запросов
            
@touch($image_path$image_meta['date_updated']);

            
$path $image_meta['dispenser_path'];

            foreach (
$this->_server_list as $i => $server){
                if (
$data $this->fetch_remote_file($server$path)) {
                    if (
substr($data012) == 'FATAL ERROR:') {
                        
$this->raise_error($data);
                    } else {
                        
// [псевдо]проверка целостности:
                        
if (strlen($data) > 0) {
                            
$this->_write($image_path$data);
                            break;
                        }
                    }
                }
            }
        }

        unset(
$data);
        if (!
is_file($image_path)) {
            return 
$this->_return_not_found();
        }
        
$image_file_meta = @getimagesize($image_path);
        
$content_type = isset($image_file_meta['mime'])?$image_file_meta['mime']:'image';
        if (
$this->_headers_enabled) {
            
header('Content-Type: ' $content_type);
        }
        return 
$this->_read($image_path);
    }

    function 
_fetch_article($template){
        if (
strlen($this->_charset)) {
            
$template str_replace('{meta_charset}',  $this->_charset$template);
        }
        foreach (
$this->_data['index']['template_fields'] as $field){
            if (isset(
$this->_data['article'][$field])) {
                
$template str_replace('{' $field '}',  $this->_data['article'][$field], $template);
            } else {
                
$template str_replace('{' $field '}',  ''$template);
            }
        }
        return (
$template);
    }

    function 
_get_template($template_url$templateId){
        
//Загрузим индекс если есть
        
$this->_save_file_name 'tpl.articles.db';
        
$index_file $this->_get_db_file();

        if (
file_exists($index_file)) {
            
$this->_data['templates'] = unserialize($this->_read($index_file));
        }


        
//Если шаблон не найден или устарел в индексе, обновим его
        
if (!isset($this->_data['templates'][$template_url])
            or (
time() - $this->_data['templates'][$template_url]['date_updated']) > $this->_data['index']['templates'][$templateId]['lifetime']) {
            
$this->_refresh_template($template_url$index_file);
        }
        
//Если шаблон не обнаружен - ошибка
        
if (!isset($this->_data['templates'][$template_url])) {
            if (
$this->_template_error){
                return 
$this->raise_error($this->_template_error);
            }
            return 
$this->raise_error('Не найден шаблон для статьи');
        }

        return 
$this->_data['templates'][$template_url]['body'];
    }

    function 
_refresh_template($template_url$index_file){
        
$parseUrl parse_url($template_url);

        
$download_url '';
        if (
$parseUrl['path']) {
            
$download_url .= $parseUrl['path'];
        }
        if (isset(
$parseUrl['query'])) {
            
$download_url .= '?' $parseUrl['query'];
        }

        
$template_body $this->fetch_remote_file($this->_real_host$download_urltrue);

        
//проверим его на корректность
        
if (!$this->_is_valid_template($template_body)){
            return 
false;
        }

        
$template_body $this->_cut_template_links($template_body);

        
//Запишем его вместе с другими в кэш
        
$this->_data['templates'][$template_url] = array( 'body' => $template_body'date_updated' => time());
        
//И сохраним кэш
        
$this->_write($index_fileserialize($this->_data['templates']));
    }

    function 
_fill_mask ($data) {
        global 
$unnecessary;
        
$len strlen($data[0]);
        
$mask str_repeat($this->_mask_code$len);
        
$unnecessary[$this->_mask_code][] = array(
            
'mask' => $mask,
            
'code' => $data[0],
            
'len'  => $len
        
);

        return 
$mask;
    }

    function 
_cut_unnecessary(&$contents$code$mask) {
        global 
$unnecessary;
        
$this->_mask_code $code;
        
$_unnecessary[$this->_mask_code] = array();
        
$contents preg_replace_callback($mask, array($this'_fill_mask'), $contents);
    }

    function 
_restore_unnecessary(&$contents$code) {
        global 
$unnecessary;
        
$offset 0;
        if (!empty(
$unnecessary[$code])) {
            foreach (
$unnecessary[$code] as $meta) {
                
$offset strpos($contents$meta['mask'], $offset);
                
$contents substr($contents0$offset)
                    . 
$meta['code'] . substr($contents$offset $meta['len']);
            }
        }
    }

    function 
_cut_template_links($template_body) {
        if(
function_exists('mb_internal_encoding') && strlen($this->_charset) > 0) {
        
mb_internal_encoding($this->_charset);
    }
        
$link_pattern    '~(<a [^>]*?href[^>]*?=["']{0,1}http[^>]*?>.*?</a[^>]*?>|<a [^>]*?href[^>]*?=["']{0,1}http[^>]*?>|<area [^>]*?href[^>]*?=["']{0,1}http[^>]*?>)~si';
        $link_subpattern = '~<a |<area ~si';
        $rel_pattern     = '~[s]{1}rel=["']{1}[^ "'>]*?["']{1}| rel=[^ "'>]*?[s]{1}~si';
        $href_pattern    = '~[s]{1}href=["']{0,1}(http[^ "'>]*)?["']{0,1} {0,1}~si';

        $allowed_domains = $this->_data['index']['ext_links_allowed'];
        $allowed_domains[] = $this -> _host;
        $allowed_domains[] = 'www.' . $this -> _host;
        $this->_cut_unnecessary($template_body, 'C', '|<!--(.*?)-->|smi');
        $this->_cut_unnecessary($template_body, 'S', '|<script[^>]*>.*?</script>|si');
        $this->_cut_unnecessary($template_body, 'N', '|<noindex[^>]*>.*?</noindex>|si');

        $slices = preg_split($link_pattern, $template_body, -1,  PREG_SPLIT_DELIM_CAPTURE );
        //Обрамляем все видимые ссылки в noindex
        if(is_array($slices)) {
            foreach ($slices as $id => $link) {
                if ($id % 2 == 0) {
                    continue;
                }
                if (preg_match($href_pattern, $link, $urls)) {
                    $parsed_url = @parse_url($urls[1]);
                    $host = isset($parsed_url['host'])?$parsed_url['host']:false;
                    if (!in_array($host, $allowed_domains) || !$host){
                        //Обрамляем в тэги noindex
                        $slices[$id] = '<noindex>' . $slices[$id] . '</noindex>';
                    }
                }
            }
            $template_body = implode('', $slices);
        }
        //Вновь отображаем содержимое внутри noindex
        $this->_restore_unnecessary($template_body, 'N');

        //Прописываем всем ссылкам nofollow
        $slices = preg_split($link_pattern, $template_body, -1,  PREG_SPLIT_DELIM_CAPTURE );
        if(is_array($slices)) {
            foreach ($slices as $id => $link) {
                if ($id % 2 == 0) {
                    continue;
                }
                if (preg_match($href_pattern, $link, $urls)) {
                    $parsed_url = @parse_url($urls[1]);
                    $host = isset($parsed_url['host'])?$parsed_url['host']:false;
                    if (!in_array($host, $allowed_domains) || !$host) {
                        //вырезаем REL
                        $slices[$id] = preg_replace($rel_pattern, '', $link);
                        //Добавляем rel=nofollow
                        $slices[$id] = preg_replace($link_subpattern, '$0rel="nofollow" ', $slices[$id]);
                    }
                }
            }
            $template_body = implode('', $slices);
        }

        $this->_restore_unnecessary($template_body, 'S');
        $this->_restore_unnecessary($template_body, 'C');
        return $template_body;
    }

    function _is_valid_template($template_body){
        foreach ($this->_data['index']['template_required_fields'] as $field){
            if (strpos($template_body, '{' . $field . '}') === false){
                $this->_template_error = 'В шаблоне не хватает поля ' . $field . '.';
                return false;
            }
        }
        return true;
    }

    function _return_html($html){
        if ($this->_headers_enabled){
            header('HTTP/1.x 200 OK');
            if (!empty($this->_charset)){
                    header('Content-Type: text/html; charset=' . $this->_charset);
            }
        }
        return $html;
    }

    function _return_not_found(){
        header('HTTP/1.x 404 Not Found');
    }

    function _get_dispenser_path(){
        switch ($this->_request_mode){
            case 'index':
                return '/?user=' . _SAPE_USER . '&host=' .
                $this->_host . '&rtype=' . $this->_request_mode;
            break;
            case 'article':
                return '/?user=' . _SAPE_USER . '&host=' .
                $this->_host . '&rtype=' . $this->_request_mode . '&artid=' . $this->_article_id;
            break;
            case 'image':
                return $this->image_url;
            break;
        }
    }

    function _set_request_mode($mode){
        $this->_request_mode = $mode;
    }

    function _get_db_file(){
        if ($this->_multi_site){
            return dirname(__FILE__) . '/' . $this->_host . '.' . $this->_save_file_name;
        }
        else{
            return dirname(__FILE__) . '/' . $this->_save_file_name;
        }
    }

    function set_data($data){
       $this->_data[$this->_request_mode] = $data;
    }

}

?>
Онлайн: 1
Реклама