/** * */ public function requestParser($template) { if (!user_allowed_to('search')) { return $template; } if (!isset($_GET['module']) || $_GET['module'] != 'search' || !isset($_GET['search'])) { return $template; } // generated HTML will be here // some init $this->chars_to_include = get_array_value($this->CONFIG, 'chars_to_include', 60); $wrap_tag = get_array_value($this->CONFIG, 'wrap_tag', 'b'); $xml = new DOMDocument('1.0', 'utf-8'); $xml->preserveWhiteSpace = false; $xml->formatOutput = true; $root_node = $xml->createElement('search-results'); $xml->appendChild($root_node); // parse search string $search_pattern = preg_replace('~[.,:;\\(\\)\\-\\\\/\'\\"]+~', ' ', $_GET['search']); if (preg_match_all('~[^\\s]{2,}~smui', $search_pattern, $matches) == 0) { $template = preg_replace(macro_regexp('content'), 'Некорректный запрос', $template); return $template; } $search = $matches[0]; // enumarate all user pages if content module exists if (module_get_config('content', $content_module_config) === true) { $files = scandir('userfiles/pages/'); foreach ($files as $file) { // skip some files (".", "..", .htaccess) if (substr($file, 0, 1) == '.') { continue; } // skip generator pages if (pathinfo($file, PATHINFO_EXTENSION) == 'php') { continue; } // ok, let's test this $content = file_get_contents('userfiles/pages/' . $file); if ($highlighted = $this->highlightPatternsItTheString($search, $content, $wrap_tag)) { // get title and link, skip if filename is not in the base (possibly means corrupted database) $query = CMS::$DB->query("select alias, title from `{$content_module_config['config']['table']}` where filename = '{$file}'"); if ($row = $query->fetch(PDO::FETCH_ASSOC)) { $root_node->appendChild($more_node = $xml->createElement('result')); $more_node->appendChild($xml->createElement('alias'))->nodeValue = $row['alias']; $more_node->appendChild($xml->createElement('title'))->nodeValue = $row['title']; $more_node->appendChild($xml->createElement('highlight'))->appendChild($xml->createCDATASection($highlighted)); } } } } // also look up at news if (module_get_config('news', $news_module_config) === true) { $query = CMS::$DB->query("select * from `{$news_module_config['config']['table']}` order by stamp desc"); while ($data = $query->fetch(PDO::FETCH_ASSOC)) { // ok, let's test this $content = $data['summary']; if ($highlighted = $this->highlightPatternsItTheString($search, $content, $wrap_tag)) { // get title and link, skip if filename is not in the base (possibly means corrupted database) $root_node->appendChild($more_node = $xml->createElement('result')); $more_node->appendChild($xml->createElement('alias'))->nodeValue = $data['page']; $more_node->appendChild($xml->createElement('title'))->nodeValue = $data['caption']; $more_node->appendChild($xml->createElement('highlight'))->appendChild($xml->createCDATASection($highlighted)); } } } $root_node->appendChild($xml->createElement('pattern'))->nodeValue = implode($search, ' '); // final HTML $result = XSLTransform($xml->saveXML($root_node), __DIR__ . '/output.xsl'); // replace content with search results $template = preg_replace(macro_regexp('content'), $result, $template); // replace page title $template = preg_replace(macro_regexp('page_title'), 'Поиск: ' . implode($search, ' '), $template); return $template; }
/** * Updates menu element record * * @param array $input data to use. It may specially prepared array or even unfiltered POST/GET input * @return mixed true on success, message string on failure */ private function elementUpdate($input) { // configuration check if (!preg_match(REGEXP_IDENTIFIER, $this->CONFIG['table_menu'])) { return 'некорректное имя таблицы'; } $table = $this->CONFIG['table_menu']; // filter input $input_filter = array('id' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^-?[0-9]+$~ui')), 'alias' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => REGEXP_ALIAS)), 'parent' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[0-9]+$~ui')), 'caption' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Za-яА-Я\\s0-9/\\-_:.,=+!@#$%^&*()"]+$~ui')), 'page' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => REGEXP_ALIAS)), 'link' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(https?://)?[a-zA-Z0-9\\-/.,=&?_]+(\\?.*)?$~i')), 'picture' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9\\-_.]+\\.(jpg|jpeg|gif|png)$~ui')), 'text' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Za-яА-Я\\s0-9\\-_:.,=+!@#$%^&*()<>"/]+$~smui')), 'style_content' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9\\-]+$~ui')), 'style_item' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(([a-zA-Z\\-]+\\s*:\\s*[a-zA-Z0-9\\-;%\\s]+)+|[a-zA-Z0-9\\s\\-_]+)$~ui')), 'class_item' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z\\-][a-zA-Z0-9\\-\\s]*$~ui')), 'add_more' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Za-яА-Я\\s0-9\\-_:]+$~ui')), 'hidden' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(on|)$~ui')), 'title' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9а-яА-Я\\s\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\,\\.\\?\\:\\№]+$~ui')), 'meta' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^.*$~smui'))); $_INPUT = get_filtered_input($input_filter); // shorthand $element_id = $_INPUT['id']; // some special mode $insert_mode = $element_id < 0; // pull existing values to replace incorrect input $q = CMS::$DB->query("select * from {$table} where id = {$element_id}"); if ($current = $q->fetch(PDO::FETCH_ASSOC)) { foreach ($current as $index => $value) { if (isset($_INPUT[$index]) && $_INPUT[$index] == '' && (@$_POST[$index] > '' || @$_GET[$index] > '') && $value > '') { // all that mean that input was incorrect $_INPUT[$index] = $value; } } } // on insert, we will need new ordermark to $new_ordermark = CMS::$DB->querySingle("select ifnull(max(ordermark),0)+1 from {$table}"); // choose the proper SQL $sql = $insert_mode ? " insert into {$table} " . " ( parent_id, caption, page, link, ordermark, alias, text, picture, style_content, style_item, class_item, hidden, title, meta ) " . " values " . " (:parent_id, :caption, :page, :link, :ordermark, :alias, :text, :picture, :style_content, :style_item, :class_item, :hidden, :title, :meta ) " : " update {$table} set " . " parent_id = :parent_id, " . " caption = :caption, " . " page = :page, " . " link = :link, " . " alias = :alias, " . " text = :text, " . " picture = :picture, " . " style_content = :style_content, " . " style_item = :style_item, " . " class_item = :class_item, " . " hidden = :hidden, " . " title = :title, " . " meta = :meta " . " where id = :id "; // take caption from linked page title if not set, cancel if nothing found if ($_INPUT['caption'] == '') { if ($_INPUT['title'] > '') { $_INPUT['caption'] = $_INPUT['title']; } else { if (module_get_config('content', $content_module_config)) { $_INPUT['caption'] = CMS::$DB->querySingle("select title from `{$content_module_config['config']['table']}` where alias = '{$_INPUT['link']}'"); } } } if ($_INPUT['caption'] == '') { return 'Некорректный заголовок'; } $query_params = array('id' => $_INPUT['id'], 'parent_id' => $_INPUT['parent'], 'caption' => $_INPUT['caption'], 'page' => trim($_INPUT['page'] == '') ? '' : $_INPUT['page'], 'link' => $_INPUT['link'], 'ordermark' => $new_ordermark, 'alias' => trim($_INPUT['alias']) > '' ? $_INPUT['alias'] : strtolower(create_guid()), 'text' => $_INPUT['text'], 'picture' => $_INPUT['picture'], 'style_content' => $_INPUT['style_content'], 'style_item' => $_INPUT['style_item'], 'class_item' => $_INPUT['class_item'], 'hidden' => $_INPUT['hidden'] > '' ? 1 : 0, 'title' => $_INPUT['title'], 'meta' => $_INPUT['meta']); // some items are unnercessary when inserting or updating, PDO will get mad of them, so remove them! if ($insert_mode) { unset($query_params['id']); } else { unset($query_params['ordermark']); } // ok, go $prepared = CMS::$DB->prepare($sql); if ($prepared->execute($query_params) == false) { return $prepared->errorInfo[2] . ')'; } return true; }
function contentGenerator($template) { $USERFILES_DIRS = CMS::$R['USERFILES_DIRS']; // если этот флажок есть, будет вызван редактор вместо отображения контента $edit_mode = isset($_GET['edit']); // идентификатор странички, которую надо вставить в шаблон. валидация не нужна - делается поиск в массиве // собираем список имеющихся страниц $pages = array(); $query = CMS::$DB->query("select * from `{$this->CONFIG['table']}`"); while ($row = $query->fetch(PDO::FETCH_ASSOC)) { $pages[$row['alias']] = $row; } $page_id = isset($_GET['p_id']) ? $_GET['p_id'] : DEFAULT_PAGE_ALIAS; // ок, берем стандартную страницу, если таковая есть $page_found = false; if (isset($pages[$page_id])) { $page_found = true; $page_info = $pages[$page_id]; } else { // если нужного идентификатора нет в страницах, посмотрим в меню, если там найдется - пускай сами разбираются if (module_get_config('menu', $menu_module_config) === true) { $query = CMS::$DB->query("select alias from `{$menu_module_config['config']['table_menu']}` where alias > ''"); while ($row = $query->fetch(PDO::FETCH_ASSOC)) { if ($page_id == $row['alias']) { $page_found = true; return $template; } } } } // если страница не найдена, попробуем использовать то, что указано в настройках для страницы 404, // если и там нету - тупо заменяем макрос на строку и вываливаемся if (!$page_found) { header('HTTP/1.1 404 Not found'); if (isset($pages[$this->CONFIG['page_404']])) { $page_info = $pages[$this->CONFIG['page_404']]; } else { $template = preg_replace(macro_regexp('content'), 'Страница не найдена', $template); return $template; } } // имя файла с контентом $content_filename = isset($page_info['filename']) && file_exists($USERFILES_DIRS['pages']['dir'] . $page_info['filename']) ? $USERFILES_DIRS['pages']['dir'] . $page_info['filename'] : $this->CONFIG['page_404']; // в режиме редактирования текст/xml не генерируем, а показываем в редакторе (textarea) if ($edit_mode && user_allowed_to('edit pages')) { switch (pathinfo($page_info['filename'], PATHINFO_EXTENSION)) { case 'php': case 'xml': $pagehtml = sprintf(MODULE_CONTENT_TEXTAREA_WRAPPER_PHP, $page_id, @file_get_contents($content_filename)); break; default: $pagecontent = @file_get_contents($content_filename); // при редактировании заменим макросы на защищенную версию, иначе следующие модули на них среагируют // и заменят на свой контент, что наи не нужно. ядро само заменит их обратно потом $pagecontent = str_replace('<macro', '<protected-macro', $pagecontent); $pagecontent = str_replace('[macro', '[protected-macro', $pagecontent); $pagecontent = str_replace('</macro', '</protected-macro', $pagecontent); $pagecontent = str_replace('[/macro', '[/protected-macro', $pagecontent); $pagehtml = sprintf(MODULE_CONTENT_TEXTAREA_WRAPPER, $page_id, $pagecontent); break; } } else { // если html, тащим как есть, иначе формируем с помошью генератора или XSLT switch ($ext = pathinfo($content_filename, PATHINFO_EXTENSION)) { case 'php': include_once $content_filename; $pagehtml = call_user_func($page_info['generator']); break; case 'xml': $pagehtml = XSLTransform($content_filename, $USERFILES_DIRS['xsl']['dir'] . $page_info['xsl'], false, false); break; default: ($pagehtml = file_get_contents($content_filename)) !== false or $pagehtml = 'error reading page content (code CONTENT/001)'; break; } } // если есть BODY, берем его внутреннее содержимое, иначе весь файл целиком if (preg_match(self::REGEXP_HTML_BODY, $pagehtml, $page_body) > 0) { $replace = $page_body[1]; } else { $replace = $pagehtml; } if (isset($_GET['print'])) { $template = str_replace('%content%', $replace, MODULE_CONTENT_PRINT_FORM); } else { $template = preg_replace(macro_regexp('content'), $replace, $template); } // мета в заголовке. если только буквы-цифры, делаем мету keywords if (preg_match('~^[a-zA-Zа-яА-Я0-9,.\\-\\s]+$~ui', $page_info['meta'], $match)) { $template = add_meta($template, 'name', 'keywords', $match[0]); } elseif (preg_match_all('~(\\(([a-zA-Z\\-]*)\\|([a-zA-Z\\-0-9]+)\\|([a-zA-Z\\-0-9а-яА-Я.,;:\\s+=!@#$%^&*\\(\\)]*)\\))~smui', $page_info['meta'], $matches)) { // не прокатило, попробуем структуру со скобками и пайпами for ($i = 0; $i < count($matches[0]); $i++) { $template = add_meta($template, $matches[2][$i], $matches[3][$i], $matches[4][$i]); } } elseif (preg_match_all('~<meta\\s[^>]+>~smui', $page_info['meta'], $matches)) { // проверим, возможно вписали сырые теги for ($i = 0; $i < count($matches[0]); $i++) { $template = str_insert_before('</head>', $matches[0][$i] . PHP_EOL, $template); } } // заменяем залоговок страницы, если определен if (isset($page_info['title']) && ($replace = $page_info['title']) > '') { $template = preg_replace(macro_regexp('page_title'), $replace, $template, 1); } // кастомный CSS, если указан if (isset($page_info['custom_css']) && ($css = $page_info['custom_css']) > '') { add_CSS(CMS::$R['USERFILES_DIRS']['css']['dir'] . $css); } // кастомный JS, если указан if (isset($page_info['custom_js']) && ($js = $page_info['custom_js']) > '') { add_JS(CMS::$R['USERFILES_DIRS']['js']['dir'] . $js); } return $template; }
/** * Creates XML structure with all modules wich can respond to "p_id" parameter in _GET (such as content and menus in catalog mode) * * @param array $options XML options: * root (string) : root node name * use (array) : modules to scan (items or "*") * skip (array) : filter array with modules names to use * @return DOMDocument */ function aliasCatchersAsXML($options = array('root' => 'alias-catchers', 'use' => array('*'), 'skip' => array())) { $xml = new DOMDOcument('1.0', 'utf-8'); $root_node_name = get_array_value($options, 'root', 'alias-catchers'); $xml->appendChild($root_node = $xml->createElement($root_node_name)); $skip_modules = get_array_value($options, 'skip', array()); $use_modules = get_array_value($options, 'skip', array('*')); // content module if ((in_array('*', $use_modules) || in_array('content', $use_modules)) && !in_array('content', $skip_modules)) { if (($content_config_ok = module_get_config('content', $content_config)) && ($pages_table = get_array_value($content_config['config'], 'table', false, REGEXP_IDENTIFIER)) != false) { $root_node->appendChild($module_node = $xml->createElement('module'))->setAttribute('name', 'Страницы'); $query = CMS::$DB->query("select alias, title from `{$pages_table}` order by title"); while ($row = $query->fetch(PDO::FETCH_ASSOC)) { $module_node->appendChild($catcher_node = $xml->createElement('catcher')); $catcher_node->appendChild($xml->createElement('title'))->nodeValue = $row['title']; $catcher_node->appendChild($xml->createElement('alias'))->nodeValue = $row['alias']; } } } // menu module if ((in_array('*', $use_modules) || in_array('menu', $use_modules)) && !in_array('menu', $skip_modules)) { if ($menu_config_ok = module_get_config('menu', $menu_config)) { $root_node->appendChild($module_node = $xml->createElement('module'))->setAttribute('name', 'Каталоги'); if (($menu_table = get_array_value($menu_config['config'], 'table_menu', false, REGEXP_IDENTIFIER)) != false) { $query = CMS::$DB->query("select alias, caption from `{$menu_table}` where alias > ''order by caption"); while ($row = $query->fetch(PDO::FETCH_ASSOC)) { $module_node->appendChild($catcher_node = $xml->createElement('catcher')); $catcher_node->appendChild($xml->createElement('title'))->nodeValue = $row['caption']; $catcher_node->appendChild($xml->createElement('alias'))->nodeValue = $row['alias']; } } } } return $xml; }