/** * */ public function requestParser($template) { if (!user_allowed_to('backup works')) { return $template; } $merged_post_get = array_merge($_GET, $_POST); if (!isset($merged_post_get['module']) || $merged_post_get['module'] != 'backup') { return $template; } $input_filter = array('backup_name' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9_\\-]+(|\\.zip)$~ui')), 'backup_description' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9_\\s\\-а-яА-Я.:;"]+$~ui')), 'action' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(create|restore|delete|download)+$~ui')), 'result' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z_]+$~ui'))); $_INPUT = get_filtered_input($input_filter); $result_text = 'Неизвестное действие'; $result_class = 'backup_result_bad'; switch ($_INPUT['action']) { case 'create': if ($_INPUT['backup_name'] == '') { popup_message_add('Некорректное имя файла', JCMS_MESSAGE_ERROR); break; } // force extension if (substr($_INPUT['backup_name'], -4) != '.zip') { $_INPUT['backup_name'] .= '.zip'; } if (($result = $this->createBackup($_INPUT['backup_name'], $_INPUT['backup_description'])) === true) { popup_message_add('Резервная копия создана', JCMS_MESSAGE_OK); } else { popup_message_add('Не удалось создать резервную копию', JCMS_MESSAGE_ERROR); } terminate('', 'Location: ./?module=backup&action=manage', 302); break; case 'restore': if (($result = $this->restoreBackup($_INPUT['backup_name'])) === true) { popup_message_add('Резервная копия восстановлена', JCMS_MESSAGE_OK); } else { popup_message_add('Не удалось восстановить резервную копию (' . $result . ')', JCMS_MESSAGE_ERROR); } terminate('', 'Location: ./?module=backup&action=manage', 302); break; case 'delete': if ($this->deleteBackup($_INPUT['backup_name'])) { popup_message_add('Резервная копия удалена', JCMS_MESSAGE_OK); } else { popup_message_add('Не удалось удалить резервную копию (' . $result . ')', JCMS_MESSAGE_ERROR); } terminate('', 'Location: ./?module=backup&action=manage', 302); break; case 'download': header('HTTP/1.1 200 OK'); header('Content-Length: ' . filesize(__DIR__ . '/data/' . $_INPUT['backup_name'])); header('Content-Type: octet/stream'); header('Content-Transfer-Encoding: 8bit'); header('Content-Disposition: attachment; filename*=UTF-8\'\'' . str_replace('+', '%20', urlencode(iconv('windows-1251', 'utf-8', $_INPUT['backup_name']))) . ''); readfile(__DIR__ . '/data/' . $_INPUT['backup_name']); exit; break; } return $template; }
/** * */ function requestParser($template) { if (!user_allowed_to('manage files')) { return $template; } $module_name = 'filemanager'; // check if something to do if (@$_GET['module'] != $module_name && @$_POST['module'] != $module_name) { return $template; } // filter input $input_filter = array('action' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(update_file|upload|delete)$~ui')), 'category' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => REGEXP_ALIAS)), 'filename' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(?!(\\.\\.|\\|//|[a-zA-Zа-яА-Я0-9\\s_\\-\\(\\)]:)).*$~u')), 'new_filename' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(?!(\\.\\.|\\|//|[a-zA-Zа-яА-Я0-9\\s_\\-\\(\\)]:)).*$~u')), 'filecontent' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~.*~'))); $_INPUT = get_filtered_input($input_filter); // prepare redirect $redirect_target = './?module=' . $module_name . '&action=manage&category=' . $_INPUT['category']; $redirect_status = false; switch (get_array_value($_INPUT, 'action')) { case 'upload': for ($i = 0; $i < count($_FILES['files']['name']); $i++) { // check extension against directory configuration, use only if matches if (($dir = $this->getUserFolderParams($_FILES['files']['name'][$i], $_INPUT['category'])) != false) { move_uploaded_file($_FILES['files']['tmp_name'][$i], iconv('utf-8', filesystem_encoding(), $dir['dir'] . $_FILES['files']['name'][$i])); } } $redirect_status = true; break; case 'delete': if ($this->getUserFolderParams($_INPUT['filename']) != false) { unlink($_INPUT['filename']); } $redirect_status = true; break; case 'update_file': // check if filenames (old and new) are ok if ($this->getUserFolderParams($_INPUT['filename']) === false || $this->getUserFolderParams($_INPUT['new_filename']) === false) { popup_message_add('Расширение не подходит для этой папки', JCMS_MESSAGE_ERROR); return $template; } // write contents, yeah file_put_contents(iconv('utf-8', filesystem_encoding(), $_INPUT['filename']), $_INPUT['filecontent']); // rename if requested if ($_INPUT['filename'] != $_INPUT['new_filename']) { rename($_INPUT['filename'], $_INPUT['new_filename']); } popup_message_add('Файл обновлен', JCMS_MESSAGE_OK); $redirect_status = true; break; } // check for redirect if ($redirect_status) { terminate('', 'Location: ' . $redirect_target, 302); }
/** * Just a proxy for element-changing functions * * @param string template to modify * @return string modified (or not) template */ function requestParser($template) { if (@$_POST['module'] != 'menu' && @$_GET['module'] != 'menu' || !user_allowed_to('manage menu')) { return $template; } $_INPUT = array_merge($_GET, $_POST); // check & sure if "action" parameter is set and set once only switch (@$_POST['action'] . @$_GET['action']) { // avoid circular redirecting case 'manage': return $template; break; // yeah, just an updating // yeah, just an updating case 'update': if (($result = $this->elementUpdate($_INPUT)) !== true) { popup_message_add('[MENU] ошибка сохранения записи: ' . $result, JCMS_MESSAGE_ERROR); } break; // move the upper // move the upper case 'moveup': if (($result = $this->elementMoveUp($_INPUT['id'])) !== true) { popup_message_add('[MENU] ошибка изменения порядка элементов: ' . $result, JCMS_MESSAGE_ERROR); } break; // movibg down // movibg down case 'movedown': if (($result = $this->elementMoveDown($_INPUT['id'])) !== true) { popup_message_add('[MENU] ошибка изменения порядка элементов: ' . $result, JCMS_MESSAGE_ERROR); } break; // deleting the item // deleting the item case 'delete': if (($result = $this->elementDelete($_INPUT['id'])) !== true) { popup_message_add('[MENU] удаления элемента: ' . $result, JCMS_MESSAGE_ERROR); } $_INPUT['id']; break; default: popup_message_add('[ MENU ] unknown action', JCMS_MESSAGE_WARNING); break; } terminate('', 'Location: ./?module=menu&action=manage', 302); }
/** * Admin! * */ function adminGenerator() { if (($table = get_array_value($this->CONFIG, 'table', false, '~^[a-zA-Z_][a-zA-Z_0-9]*$~')) == false) { popup_message_add('[ NEWS ] table not defined or configuration error', JCMS_MESSAGE_ERROR); return false; } // get all news $query = CMS::$DB->query("select stamp, id, caption, link, page, streams, summary from `{$table}`"); if ($query == false) { popup_message_add('Query error: ' . get_array_value(CMS::$DB->errorInfo(), 2), JCMS_MESSAGE_ERROR); return false; } // format all items at a time into XML and then transform to HTML $xml = array_to_xml($query->fetchAll(PDO::FETCH_ASSOC), array('all-news-list', 'news')); return XSLTransform($xml->saveXML($xml->documentElement), __DIR__ . '/list.xsl'); }
/** * Converts XML from string to array * * @param string $xml_string string containing XML * @return mixed false on error, array on success */ public static function fromString($xml_string) { $xml = new DOMDocument('1.0', 'utf-8'); ob_start(); $xml_parsed_ok = $xml->loadXML($xml_string); $result = ob_get_clean(); if (!$xml_parsed_ok) { popup_message_add('oops!<br />' . $result, JCMS_MESSAGE_WARNING); return false; } return self::fromXML($xml); }
/** * */ function requestParser($template) { $USERFILES_DIRS = CMS::$R['USERFILES_DIRS']; // в некоторых ситуациях требуется прервать дальнейшую обработку и перенаправить на админку снова $redirect_target = './?module=content&action=manage'; $redirect_status = false; // фильтруем вход $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)), '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')), 'filename' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9\\-\\_.]+\\.(html|php|xml)$~ui')), 'css' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9\\-\\_.]+\\.css$~ui')), 'js' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9\\-\\_.]+\\.js$~ui')), 'generator' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z\\_][a-zA-Z0-9\\_]*$~ui')), 'p_id' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => REGEXP_ALIAS)), 'xsl' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z0-9\\-\\_.]+\\.xslt?$~ui')), 'pagecontent' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^.*$~smui')), 'action' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z\\_0-9]+$~ui')), 'module' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Z\\_0-9]+$~ui'))); $_INPUT = get_filtered_input($input_filter); // обновление информации о странице if (@$_INPUT['module'] == 'content' && @$_INPUT['action'] == 'update') { if (!user_allowed_to('manage pages')) { terminate('Forbidden', '', 403); } $sql_insert = 'insert into `' . $this->CONFIG['table'] . '` (alias, title, filename, custom_css, custom_js, generator, xsl, meta) values (\'%2$s\', \'%3$s\', \'%4$s\', \'%5$s\', \'%6$s\', \'%7$s\', \'%8$s\', \'%9$s\')'; $sql_update = 'update `' . $this->CONFIG['table'] . '` set alias=\'%2$s\', title=\'%3$s\', filename=\'%4$s\', custom_css=\'%5$s\', custom_js=\'%6$s\', generator=\'%7$s\', xsl=\'%8$s\', meta=\'%9$s\' where id=%1$s'; // проверим, нет ли такого алиаса с другим ID if (CMS::$DB->querySingle('select count(*) from `' . $this->CONFIG['table'] . '` where alias=\'' . $_INPUT['alias'] . '\' and id<>\'' . $_INPUT['id'] . '\'') != '0') { popup_message_add('Такой псевдоним уже существует', JCMS_MESSAGE_WARNING); return $template; //terminate('', 'Location: '.$redirect_target, 302); } // выбираем нужный шаблон SQL $sql = $_INPUT['id'] == -1 ? $sql_insert : $sql_update; // вытащим имеющиеся значения, на случай, если неправильный ввод породит пустое значение, а в базе уже непустое $q = CMS::$DB->query('select * from `' . $this->CONFIG['table'] . '` where id=' . $_INPUT['id']); if ($current = $q->fetch(PDO::FETCH_ASSOC)) { foreach ($current as $index => $value) { if (isset($_INPUT[$index]) && $_INPUT[$index] == '' && ($_POST[$index] > '' || $_GET[$index] > '') && $value > '') { $_INPUT[$index] = $value; } } } // готовим данные $filename = $_INPUT['filename'] > '' ? $_INPUT['filename'] : $_INPUT['alias'] . '.html'; // добавляем файлик с контентом, если страничка создается и странички еще нет if ($_INPUT['id'] == '-1' && !file_exists($USERFILES_DIRS['pages']['dir'] . $filename)) { switch (pathinfo($filename, PATHINFO_EXTENSION)) { case 'php': // проверим generator, если пустой - придумаем if ($_INPUT['generator'] == '') { $_INPUT['generator'] = 'get_page_content_' . $_INPUT['alias']; } $new_content = sprintf(MODULE_CONTENT_NEW_PHP_PAGE, $_INPUT['generator']); break; case 'xml': $new_content = '<root>New page</root>'; break; default: $new_content = 'New page'; break; } file_put_contents($USERFILES_DIRS['pages']['dir'] . $filename, $new_content); } // готовим и засылаем запрос // (!) порядок следования аргументов всегда фиксированный: id, alias, title, filename, custom_css, custom_js, generator, xsl, meta // (!) должно следовать после куска с записью файла, потому что там задается generator по умолчанию $sql = sprintf($sql, $_INPUT['id'], $_INPUT['alias'], $_INPUT['title'], $filename, $_INPUT['css'], $_INPUT['js'], $_INPUT['generator'], $_INPUT['xsl'], $_INPUT['meta']); CMS::$DB->query($sql); $redirect_status = true; } // удаление страницы if (@$_INPUT['module'] == 'content' && @$_INPUT['action'] == 'delete') { if (!user_allowed_to('manage pages')) { terminate('Forbidden', '', 403); } // get filename $filename = CMS::$DB->querySingle('select filename from `' . $this->CONFIG['table'] . '` where id=' . $_INPUT['id']); // удаляем запись CMS::$DB->query('delete from `' . $this->CONFIG['table'] . '` where id=' . $_INPUT['id']); // перемещаем файлик в помойку, предварительно проверим наличие помойки if (!file_exists($USERFILES_DIRS['trash']['dir'])) { mkdir($USERFILES_DIRS['trash']['dir']); } rename($USERFILES_DIRS['pages']['dir'] . $filename, $USERFILES_DIRS['trash']['dir'] . $filename); $redirect_status = true; } // обработка сохранения страницы if (@$_INPUT['module'] == 'content' && @$_INPUT['action'] == 'savepage') { if (!user_allowed_to('edit pages')) { terminate('Forbidden', '', 403); } $try_content = $_INPUT['pagecontent']; $page_id = $_INPUT['p_id']; $q = CMS::$DB->query('select * from `' . $this->CONFIG['table'] . '` where alias=\'' . $page_id . '\''); if ($row = $q->fetch(PDO::FETCH_ASSOC)) { file_put_contents($USERFILES_DIRS['pages']['dir'] . $row['filename'], $try_content); } // при сохранении тоже надо делать редирект, хоть и на самого себя - чтобы post не делался повторно по F5 $redirect_target = './' . $page_id; $redirect_status = true; } // редирект, если кто-то выше затребовал if ($redirect_status) { terminate('', 'Location: ' . $redirect_target, 302); } return $template; }
/** * */ function requestParser($template) { // some speed improvement if (@$_POST['module'] != 'feedback' && @$_GET['module'] != 'feedback') { return $template; } $input_filter = array('action' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-z_]+$~ui')), 'filename' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^[a-zA-Zа-яА-Я0-9][a-zA-Zа-яА-Я0-9_\\-\\s]*(\\.html|)$~ui')), 'filecontent' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^.*$~smui')), 'template' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => REGEXP_IDENTIFIER)), 'module' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^feedback$~ui'))); $_INPUT = get_filtered_input($input_filter); // another check as both POST and GET may contain "module" parameter but with different values if ($_INPUT['module'] != 'feedback') { return $template; } switch ($_INPUT['action']) { case 'add_template': if (!user_allowed_to('manage feedback templates')) { return $template; } if ($this->templateAddEmpty($_INPUT['filename'])) { terminate('', 'Location: ./?module=feedback&action=manage', 302); } break; case 'delete_template': if (!user_allowed_to('manage feedback templates')) { return $template; } if ($this->templateDelete($_INPUT['filename'])) { terminate('', 'Location: ./?module=feedback&action=manage', 302); } break; case 'update_template': if (!user_allowed_to('manage feedback templates')) { return $template; } if ($this->templateUpdate($_INPUT['filename'], $_INPUT['filecontent'])) { terminate('', 'Location: ./?module=feedback&action=manage', 302); } break; case 'send': // TAG_TODO вынести это в отдельный метод (или вообще использовать lib/common/... // get the first of: message template, failure template, hardcoded failure message if (($text = @file_get_contents(__DIR__ . '/templates/' . $_INPUT['template'] . '.html')) == '') { logthis('[feedback] template "' . $_INPUT['template'] . '" specified, file not exists', ZLogger::LOG_LEVEL_ERROR); if (file_exists($filename_fail_message = __DIR__ . '/templates/_error_detected.html')) { $text = file_get_contents($filename_fail_message); } else { $text = 'error reading message template ("' . $_INPUT['template'] . '"), code FEEDBACK/001)' . PHP_EOL . PHP_EOL . 'POST details:' . PHP_EOL . '%POST%'; popup_message_add($_INPUT['template']); } terminate('', 'Location: ./service_feedback_failed', 302); } // replace templates foreach ($_POST as $index => $value) { $text = str_replace('%' . $index . '%', $this->prepareToInsert($value), $text); } // also add POST and referer (may be useful on error handling) $text = str_replace('%POST%', '<pre>' . $this->prepareToInsert(print_r($_POST, 1)) . '</pre>', $text); $text = str_replace('%REFERER%', '<pre>' . $this->prepareToInsert($_SERVER['HTTP_REFERER']) . '</pre>', $text); // remove unused templates (note on lazy regexp) $text = preg_replace('~%.*?%~', '', $text); // try to use template <title> as message subject if (preg_match('~<title>(.*?)</title>~smui', $text, $match)) { $subject = $match[1]; } else { $subject = $this->CONFIG['default_subject']; } // determine addressee - from config by index or first if not found $feedback_addresses = $this->CONFIG['addresses']; $recipient = isset($_POST['recipient']) && isset($feedback_addresses[$_POST['recipient']]) ? $feedback_addresses[$_POST['recipient']] : array_shift($feedback_addresses); // send message $this->mail_send(array('to' => $recipient, 'subject' => $subject, 'text' => $text), $this->CONFIG['transport'], $send_log); // add debug dialog if requested if ($this->CONFIG['transport']['debug']) { $template = str_insert_before('</body>', '<div class="debug-dialog">' . $send_log . '</div>', $template); CMS::$lock_redirect = true; } terminate('', 'Location: ./service_feedback_ok', 302); break; } return $template; }
/** * Initializes the module and adds it to cache * * @param string $module_name module to init */ function module_init($module_name) { // check if module config exists if (!isset(CMS::$cache[$module_name]['config'])) { if (($config_result = module_get_config($module_name, $config)) !== true) { popup_message_add($config_result, JCMS_MESSAGE_ERROR); return false; } CMS::$cache[$module_name]['config'] = $config; } // third, init the module include_once MODULES_DIR . $module_name . '/' . CMS::$cache[$module_name]['config']['main_script']; if (!isset(CMS::$cache[$module_name]['object'])) { $module_class_name = CMS::$cache[$module_name]['config']['class_name']; CMS::$cache[$module_name]['object'] = new $module_class_name(); CMS::$cache[$module_name]['object']->CONFIG = get_array_value(CMS::$cache[$module_name]['config'], 'config', array()); } return true; }
function requestParser($template) { // now some bunch of samples if you don',t want to modify config file // // ! absolute redirect area, take care ! // //////////////////////////////////////////////////////// // common version //////////////////////////////////////////////////////// //if ( // (($_GET['key1',] == 'value1',) && ($_GET['key2',] == 'value2',)) // || ($_SERVER['QUERY_STRING',] == 'key1=value1&key2=value2',) // //) { // header('HTTP/1.1 301 Moved Permanently',); // header('Location: chillers',); // terminate(); //} //////////////////////////////////////////////////////// // use this if you need only some GET keys to match //////////////////////////////////////////////////////// //if (($_GET['key1',] == 'value1',) && ($_GET['key2',] == 'value2',)) { // header('HTTP/1.1 301 Moved Permanently',); // header('Location: chillers',); // terminate(); //} //////////////////////////////////////////////////////// // full match version //////////////////////////////////////////////////////// //if ($_SERVER['QUERY_STRING',] == 'key1=value1&key2=value2',) { // header('HTTP/1.1 301 Moved Permanently',); // header('Location: chillers',); // terminate(); //} //////////////////////////////////////////////////////// // absolute redirect, ignoring module call method if (isset($this->CONFIG['redirect_rules']) && is_array($this->CONFIG['redirect_rules'])) { foreach ($this->CONFIG['redirect_rules'] as $rule) { $redirect = false; if (!isset($rule['check'])) { popup_message_add('Redirect: no "check" section found, skipping rule', JCMS_MESSAGE_WARNING); continue; } $check_this = $rule['check']; // if rule is string, check entire query string if (is_string($check_this)) { $redirect = $_SERVER['QUERY_STRING'] == $check_this; } // if rule is array, check all pairs if (is_array($check_this)) { $redirect = count(array_diff($check_this, $_GET)) == 0; } // ok, we need to redirect if ($redirect) { // first use default code as default ;-) $http_code = self::DEFAULT_HTTP_CODE; // if location specified, use 301 if (isset($rule['location'])) { $http_code = 301; } // if code set explicitly, use if correct if (isset($rule['code']) && isset($this->http_code_texts[$rule['code']])) { $http_code = $rule['code']; } // send special headers for special cases switch ($http_code) { case '301': header('Location: ' . $rule['location']); break; } terminate($this->http_code_texts[$http_code], '', $http_code); } } } if (@$_POST['module'] == 'redirect' || @$_GET['module'] == 'redirect') { // yeah filter input $input_filter = array('action' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => '~^(redirect|no_redirect)$~ui')), 'target' => array('filter' => FILTER_VALIDATE_REGEXP, 'options' => array('regexp' => REGEXP_ALIAS))); $R = get_filtered_input($input_filter, array(FILTER_GET_FULL, FILTER_POST_FULL)); switch ($R['action']) { // explicit redirect case 'redirect': header('Location: ./' . $R['target']); terminate(); break; } } return $template; }